home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / quicktime / timecodes / qttimecode / common files / macframework.c < prev    next >
Encoding:
Text File  |  2000-06-23  |  53.6 KB  |  2,026 lines

  1. //////////
  2. //
  3. //    File:        MacFramework.c
  4. //
  5. //    Contains:    Basic support for playing QuickTime and QuickTime VR movies in a Macintosh application.
  6. //                MacFramework is a simple QuickTime viewer and editor framework. It handles windows,
  7. //                menus, events, and other low-level things. Put your application-specific code into the
  8. //                file ComApplication.c. 
  9. //
  10. //    Written by:    Tim Monroe
  11. //                Based on the MovieShell code written by Apple DTS (Kent Sandvik).
  12. //
  13. //    Copyright:    © 1994-1999 by Apple Computer, Inc., all rights reserved.
  14. //
  15. //    Change History (most recent first):GetFrontWindow
  16. //
  17. //       <52>         06/07/99    rtm        added GetFrontAppWindow and GetNextAppWindow; revised existing GetFrontMovieWindow
  18. //                                    and GetNextMovieWindow
  19. //       <51>         06/05/99    rtm        added gAppFSSpec to keep track of the application's location
  20. //       <50>         05/12/99    rtm        tweaked DoSaveAsMovieWindow to ensure it creates single-fork movies; renamed it
  21. //                                    as DoSaveAsMovieFile
  22. //       <49>         05/11/99    rtm        further work on DoSaveAsMovieWindow
  23. //       <48>         05/10/99    rtm        commented CloseMovieFile out of DoCreateMovieWindow; tweaked DoUpdateMovieFile
  24. //                                    and DoSaveAsMovieWindow to reflect changes
  25. //       <47>         05/06/99    rtm        added createMovieFileDontCreateResFile flag to FlattenMovieData call
  26. //                                    in DoSaveAsMovieWindow
  27. //       <46>         03/31/99    rtm        added default name for new movies; added DoSaveAsMovieWindow to implement
  28. //                                    correct "Save As" behavior
  29. //       <45>         03/18/99    rtm        added SetMoviePlayHints call in DoCreateMovieWindow to support possible
  30. //                                    dynamic resizing of streamed movies
  31. //       <44>         01/26/99    rtm        added EnableItem call for iSaveAs menu item in AdjustMenus
  32. //       <43>         12/09/98    rtm        modified inDrag case in MainEventLoop to handle non-movie windows too
  33. //       <42>         10/27/98    rtm        reworked DoCreateMovieWindow to take movie name from the FSSpec when
  34. //                                    a movie is passed in
  35. //       <41>         10/20/98    rtm        added default progress procedure for all movies (in DoCreateMovieWindow)
  36. //       <40>         10/15/98    rtm        added autostarting for streamed movies
  37. //       <39>         05/06/98    rtm        added CheckQuickTimeRegistration call to main
  38. //       <38>         04/16/98    rtm        added EventAvail loop to InitMacEnvironment
  39. //       <37>         02/13/98    rtm        added GetWindowWidth; reworked SizeWindowToMovie to call it
  40. //       <36>         02/09/98    rtm        added GetWindowReferenceFromPort
  41. //       <35>         02/02/98    rtm        added SetMenuState
  42. //       <34>         01/06/98    rtm        added DoActivateWindow call to ShowAboutBox
  43. //       <33>         12/22/97    rtm        added AdjustMenus call to HandleKeyPress, as prescribed by Inside Macintosh:
  44. //                                    Macintosh Toolbox Essentials, p. 3-78
  45. //       <32>         12/18/97    rtm        moved InitApplication call from InitMacEnvironment to main (to follow EnterMovies)
  46. //       <31>         12/15/97    rtm        added mouseDown case to StandardModalDialogEventFilter
  47. //       <30>         12/12/97    rtm        reworked DoCreateMovieWindow
  48. //       <29>         12/08/97    rtm        finished support for Save in DoDestroyMovieWindow; moved main to this file
  49. //       <28>         12/05/97    rtm        added fDirty flag to window object; begun supporting Save and Save As
  50. //       <27>         12/01/97    rtm        added gAppResFile global variable; see ShowAboutBox for details
  51. //       <26>         11/07/97    rtm        revised call to DoApplicationEventLoopAction
  52. //       <25>         10/31/97    rtm        fixed crashing bug in DoDestroyMovieWindow; see note there
  53. //       <24>         10/30/97    rtm        added GetPortFromWindowReference
  54. //       <23>         09/18/97    rtm        added GetFrontWindow and GetNextWindow
  55. //       <22>         09/11/97    rtm        added SizeWindowToMovie
  56. //       <21>         07/23/97    rtm        added GetWindowObjectFromWindow; rewrote GetWindowObjectFromFrontWindow
  57. //                                    and all other functions that previously called GetWRefCon directly
  58. //       <20>         07/18/97    rtm        added calls to new Dialog Manager standard filter proc if it's available
  59. //       <19>         07/17/97    rtm        used new Dialog Manager constants for ok and cancel;
  60. //                                    added QuitFramework (called from iQuit menu and from 'quit' Apple event)
  61. //       <18>         07/15/97    rtm        revised GetMCFromFrontWindow to use GetWindowObjectFromFrontWindow;
  62. //                                    added AdjustMenus to InitMenuBar
  63. //       <17>         07/11/97    rtm        changed event loop to call AdjustMenus only before MenuSelect;
  64. //                                    added DoApplicationEventLoopAction
  65. //       <16>         06/12/97    rtm        added standard modal dialog event filter and standard user item procedure
  66. //       <15>         06/10/97    rtm        replaced existing grow zone procedure with a better one
  67. //       <14>         06/05/97    rtm        added fCanResizeWindow to app data record, replacing an app global
  68. //       <13>         02/26/97    rtm        reworked AdjustMenus slightly; see <10> also
  69. //       <12>         02/17/97    rtm        reworked DoDestroyMovieWindow
  70. //       <11>         02/04/97    rtm        tweaked gLimitRect to fix bug #1624600
  71. //       <10>         02/03/97    rtm        Select All edit menu item now disabled for QTVR movies
  72. //       <9>         01/06/97    rtm        DoIdle now called for all open app windows
  73. //       <8>         01/02/97    rtm        added gAppInForeground flag
  74. //       <7>         12/17/96    rtm        fixed crashing bug in DoCreateMovieWindow
  75. //                                    (hitting Cancel in open dialog left wrong port setting)
  76. //       <6>         12/17/96    rtm        added GetAppDataFromFrontWindow, GetAppDataFromWindow, GetAppDataFromWindowObject
  77. //       <5>         12/09/96    rtm        added RemoveApplicationWindowObject hook to allow app-specific clean-up
  78. //       <4>         12/04/96    rtm        added support for high-level events
  79. //       <3>         12/02/96    rtm        added CheckMovieControllers function
  80. //       <2>         11/27/96    rtm        conversion to personal coding style
  81. //       <1>         12/20/94    khs        first file
  82. //       
  83. //////////
  84.  
  85. // application header files
  86. #include "MacFramework.h"
  87. #include "AppConfiguration.h"
  88.  
  89. // global variables
  90. Rect                gDefaultWindowRect;
  91. Rect                gLimitRect = {10, 10, 480, 640};    // max size for any window
  92. long                gMCFlags = kMCFlags;
  93.  
  94. Boolean             gQuitFlag = false;                    // flag that keeps track of termination state
  95. Boolean                gAppInForeground;                    // is our application in the foreground?    
  96. Boolean                gHasNewDialogCalls;                    // are the new Dialog Manager functions available?
  97.  
  98. unsigned long        gWNEsleep = kWNEDefaultSleep;        // WaitNextEvent sleep time
  99. Str255                 gWindowTitle = kDefaultWindowTitle;    // default name for created windows
  100. GrowZoneUPP            gAppGrowZoneUPP;                    // UPP to our grow zone callback
  101. ModalFilterUPP        gModalFilterUPP;                    // UPP to our custom dialog event filter
  102. UserItemUPP            gUserItemProcUPP;                    // UPP to our custom dialog user item procedure
  103. Handle                gEmergencyMemory;                    // handle to our emergency memory reserve
  104.  
  105. short                 gAppResFile = kInvalidFileRefNum;    // file reference number for this application's resource file
  106. FSSpec                gAppFSSpec;                            // file specification for the application itself
  107. Str255                gAppName;                            // the name of this application
  108.  
  109.  
  110. //////////
  111. //
  112. // main
  113. // Set up the application's execution environment; make sure QuickTime (etc.) is installed.
  114. //
  115. //////////
  116.  
  117. void main (void)
  118. {
  119.     OSErr        myErr = noErr;
  120.     
  121.     InitMacEnvironment(10L);            // 10 * MoreMasters
  122.     
  123.     if (!QTUtils_IsQuickTimeInstalled()) {
  124.         ShowWarning("\pThe QuickTime extension is not present in this system (exit)", 0);
  125.         ExitToShell();
  126.     }
  127.  
  128. #if TARGET_CPU_PPC    
  129.     if (!QTUtils_IsQuickTimeCFMInstalled()) {
  130.         ShowWarning("\pThe QuickTime PowerPlug extension is not available (exit)", 0);
  131.         ExitToShell();
  132.     }
  133. #endif 
  134.  
  135.     myErr = EnterMovies();
  136.     if (myErr != noErr) {
  137.         ShowWarning("\pCould not initialize the QuickTime environment (exit): ", myErr);
  138.         ExitToShell();
  139.     }
  140.  
  141.     // do any application-specific initialization
  142.     InitApplication(kInitAppPhase_BothPhases);
  143.  
  144.     MainEventLoop();                    // get and process commands until user quits
  145.     
  146.     ExitMovies();
  147.  
  148.     ExitToShell();
  149. }
  150.  
  151.  
  152. //////////
  153. //
  154. // InitMacEnvironment
  155. // Initialize the Macintosh runtime environment.
  156. //
  157. //////////
  158.  
  159. void InitMacEnvironment (long theNumMasters)
  160. {
  161.     long            myIndex;
  162.     EventRecord     myEvent;
  163.     short            myVRefNum;
  164.     long            myDirID;
  165.     OSErr            myErr;
  166.  
  167.     // add more space to the stack
  168.     InitStack(kExtraStackSpaceSize);
  169.             
  170.     // expand heap zone to its limit
  171.     MaxApplZone();
  172.     
  173.     // allocate master pointer blocks
  174.     for (myIndex = 0; myIndex < theNumMasters; myIndex++)
  175.         MoreMasters();
  176.     
  177.     InitGraf(&qd.thePort);
  178.     InitFonts();
  179.     InitWindows();
  180.     InitMenus();
  181.     TEInit();
  182.     InitDialogs(NULL);
  183.     InitCursor();
  184.  
  185.     // pull the application into the foreground; until an application has made a few calls
  186.     // to the Event Manager, MultiFinder keeps it in the background, and splash screens and
  187.     // alert boxes will remain in a background layer (this is documented in Tech Note #180)
  188.     for (myIndex = 1; myIndex <= kBroughtToFront; myIndex++)
  189.         myErr = EventAvail(everyEvent, &myEvent);
  190.     
  191.     // initialize and install the menu bar
  192.     InitMenubar();
  193.  
  194.     // install a grow zone procedure to handle low memory situations
  195.     gEmergencyMemory = NewHandle(kEmergencyMemorySize);
  196.     if (gEmergencyMemory != NULL) {
  197.         gAppGrowZoneUPP = NewGrowZoneProc(AppGrowZoneCallback);
  198.         SetGrowZone(gAppGrowZoneUPP);
  199.     }
  200.     
  201.     // initialize foreground/background state
  202.     gAppInForeground = true;
  203.     
  204.     // see whether the new Dialog Manager functions are available
  205.     gHasNewDialogCalls = QTUtils_TrapAvailable(_DialogDispatch);
  206.         
  207.     // create modal dialog filter and user item UPPs
  208.     gModalFilterUPP = NewModalFilterProc(StandardModalDialogEventFilter);
  209.     gUserItemProcUPP = NewUserItemProc(StandardUserItemProcedure);
  210.  
  211.     // get the application's resource file
  212.     gAppResFile = CurResFile();
  213.     
  214.     // get the application's name from the resource file
  215.     GetIndString(gAppName, kAppNameResID, kAppNameResIndex);
  216.     
  217.     // get the application's location and save it in gAppFSSpec
  218.     HGetVol(NULL, &myVRefNum, &myDirID);
  219.     FSMakeFSSpec(myVRefNum, myDirID, gAppName, &gAppFSSpec);
  220. }
  221.  
  222.  
  223. //////////
  224. //
  225. // InitStack
  226. // Add some extra space to the stack.
  227. //
  228. //////////
  229.  
  230. void InitStack (long theExtraStackSpace)
  231. {
  232.     Ptr            mySize;
  233.     
  234.     mySize = GetApplLimit();
  235.     SetApplLimit((Ptr)(mySize - theExtraStackSpace));
  236. }
  237.  
  238.  
  239. //////////
  240. //
  241. // AppGrowZoneCallback
  242. // A grow zone procedure. This is straight out of IM: Memory (pp. 1-46ff)
  243. //
  244. //////////
  245.  
  246. PASCAL_RTN long AppGrowZoneCallback (Size theBytesNeeded)
  247. {
  248. #pragma unused(theBytesNeeded)
  249.  
  250.     long        myA5;
  251.     Size        myBytesFreed;
  252.     
  253.     // get current A5; we might get called at a time that A5 isn't valid
  254.     myA5 = SetCurrentA5();
  255.     
  256.     if ((*gEmergencyMemory != NULL) && (gEmergencyMemory != GZSaveHnd())) {
  257.         EmptyHandle(gEmergencyMemory);
  258.         myBytesFreed = kEmergencyMemorySize;
  259.     } else {
  260.         myBytesFreed = 0;                        // no more memory to release    
  261.     }    
  262.         
  263.     myA5 = SetA5(myA5);
  264.     
  265.     return(myBytesFreed);
  266. }
  267.  
  268.  
  269. //////////
  270. //
  271. // InitMenubar
  272. // Set up the menu bar. This is straight out of IM: Macintosh Toolbox Essentials (pp. 3-50ff)
  273. //
  274. //////////
  275.  
  276. Boolean InitMenubar (void)
  277. {
  278.     Handle        myMenuHandle = NULL;
  279.     
  280.     myMenuHandle = GetNewMBar(mMenubar);                    // read the resource-defined menu bar
  281.     if (myMenuHandle == NULL)
  282.         return(false);
  283.     
  284.     SetMenuBar(myMenuHandle);                                // install the menus
  285.     DisposeHandle(myMenuHandle);
  286.     AppendResMenu(GetMenuHandle(mApple), 'DRVR');            // add desk accessory names to Apple menu
  287.     AdjustMenus();
  288.     DrawMenuBar();
  289.     
  290.     return(true);
  291. }
  292.  
  293.  
  294. //////////
  295. //
  296. // MainEventLoop
  297. // Retrieve and process events.
  298. //
  299. //////////
  300.  
  301. void MainEventLoop (void)
  302. {
  303.     EventRecord                myEvent;
  304.     WindowRef                myWindow;
  305.     Boolean                    isEventHandled;
  306.     short                    myWindowPart;
  307.     Rect                    myScreenRect;
  308.     Rect                    myRefreshArea;
  309.     
  310.     while (!gQuitFlag) {
  311.     
  312.         // make sure we've still got our memory reserve; reallocate it if it's been used
  313.         if ((gEmergencyMemory == NULL) || (*gEmergencyMemory == NULL))
  314.             ReallocateHandle(gEmergencyMemory, kEmergencyMemorySize);
  315.     
  316.         WaitNextEvent(everyEvent, &myEvent, gWNEsleep, NULL);
  317.         
  318.         // first, perform any application-specific event loop actions
  319.         isEventHandled = DoApplicationEventLoopAction(&myEvent);
  320.             
  321.         // then, let all active movie controllers have access to the event
  322.         if (!isEventHandled)
  323.             isEventHandled = CheckMovieControllers(&myEvent);
  324.  
  325.         // then, if this event hasn't been handled, pass it on to the case statement 
  326.         // that dispatches the event to the right function
  327.         if (!isEventHandled) {
  328.         
  329.             myWindow = FrontWindow();
  330.     
  331.             switch (myEvent.what) {
  332.                 case mouseDown:
  333.                 
  334.                     myWindowPart = FindWindow(myEvent.where, &myWindow);
  335.  
  336.                     // menu bar and window-related events:            
  337.                     switch (myWindowPart) {
  338.                         case inSysWindow:
  339.                             // a mouse click in a window belonging to a desk accessory
  340.                             SystemClick(&myEvent, myWindow);
  341.                             break;
  342.                             
  343.                         case inMenuBar:
  344.                             // a mouse click in the menu bar
  345.                             AdjustMenus();
  346.                             HandleMenuCommand(MenuSelect(myEvent.where));
  347.                             break;
  348.                             
  349.                         case inDrag: {
  350.                             WindowObject         myWindowObject = NULL;
  351.                             MovieController     myMC = NULL;
  352.                             Movie                myMovie = NULL;
  353.                             Rect                 myRect;
  354.                             
  355.                             myWindowObject = GetWindowObjectFromWindow(myWindow);
  356.                             if (myWindowObject != NULL) {
  357.                                 myMC = (**myWindowObject).fController;
  358.                                 if (myMC != NULL) {
  359.                                     myMovie = (**myWindowObject).fMovie;
  360.                                     if (myMovie != NULL) {
  361.                                         GetMovieBox(myMovie, &myRect);
  362.                                         myScreenRect = (**GetGrayRgn()).rgnBBox;
  363.                                         DragAlignedWindow(myWindow, myEvent.where, &myScreenRect, &myRect, NULL);
  364.                                     }
  365.                                 }
  366.                             } else {
  367.                                 myScreenRect = (**GetGrayRgn()).rgnBBox;
  368.                                 DragWindow(myWindow, myEvent.where, &myScreenRect);
  369.                             }
  370.                             
  371.                             break;                            
  372.                         }
  373.                             
  374.                         case inContent:
  375.                             if (myWindow != FrontWindow()) {
  376.                                 SelectWindow(myWindow);
  377.                                 MacSetPort(myWindow);
  378.                             } else {
  379.                                 HandleContentClick(myWindow, &myEvent);
  380.                             }
  381.                             
  382.                             break;
  383.                         
  384.                         case inGoAway:
  385.                             // if the window is closed, dispose the movie, the controller, and the window
  386.                             if (TrackGoAway(myWindow, myEvent.where))
  387.                                 DoDestroyMovieWindow(myWindow);
  388.                             break;
  389.                     } // end switch(myWindowPart)
  390.                     break;
  391.  
  392.                 // system-level events:
  393.                 case updateEvt:
  394.                     myWindow = (WindowReference)myEvent.message;
  395.                     if (myWindow != NULL) {
  396.                         myRefreshArea = ((**(myWindow->visRgn)).rgnBBox);
  397.                         DoUpdateWindow(myWindow, &myRefreshArea);
  398.                     }
  399.                     break;
  400.                     
  401.                 case keyDown:
  402.                 case autoKey:
  403.                     HandleKeyPress(&myEvent);
  404.                     break;
  405.                 
  406.                 case diskEvt: {
  407.                     Point            myPoint = {100, 100};
  408.                 
  409.                     if (HiWord(myEvent.message) != noErr)
  410.                         (void)DIBadMount(myPoint, myEvent.message);
  411.                     break;
  412.                 }
  413.                 
  414.                 case activateEvt:
  415.                     myWindow = (WindowReference)myEvent.message;
  416.                     
  417.                      if (IsAppWindow(myWindow)) {
  418.                         DoActivateWindow(myWindow, ((myEvent.modifiers & activeFlag) != 0 ));
  419.                     }
  420.                     break;
  421.                     
  422.                 case osEvt:
  423.                     switch ((myEvent.message >> 24) & 0x00FF) {        // get high byte of message
  424.                         case suspendResumeMessage:
  425.                         
  426.                             // set the foreground/background state
  427.                             if ((myEvent.message & resumeFlag) != 0)
  428.                                 gAppInForeground = true;
  429.                             else
  430.                                 gAppInForeground = false;
  431.                             
  432.                             // activate the front window, if there is one    
  433.                             myWindow = FrontWindow();
  434.                             if (myWindow != NULL)
  435.                                 DoActivateWindow(myWindow, !((myEvent.message & resumeFlag) == 0));
  436.                             break;
  437.                         
  438.                         case mouseMovedMessage:
  439.                             break;
  440.                     }
  441.                     break;
  442.                 
  443.                 case kHighLevelEvent:
  444.                     AEProcessAppleEvent(&myEvent);
  445.                     break;
  446.                     
  447.                 case nullEvent:
  448.                     // do idle-time processing for all open windows in our window list
  449.                     myWindow = GetFrontMovieWindow();
  450.                     while (myWindow != NULL) {
  451.                         if (gAppInForeground)
  452.                             DoIdle(myWindow);
  453.                             
  454.                         myWindow = GetNextMovieWindow(myWindow);
  455.                     }
  456.                     break;
  457.                     
  458.             } // switch (myEvent.what)
  459.         } // if (!isMovieEvent)
  460.     } // while (!gQuitFlag)
  461. }
  462.  
  463.  
  464. //////////
  465. //
  466. // HandleMenuCommand
  467. // Handle a menu selection.
  468. //
  469. //////////
  470.  
  471. void HandleMenuCommand (long theMenuResult)
  472. {
  473.     short        myMenuID, myMenuItem;
  474.     Str255        myDAName;
  475.     
  476.     MacSetCursor(&qd.arrow);
  477.  
  478.     myMenuID = HiWord(theMenuResult);
  479.     myMenuItem = LoWord(theMenuResult);
  480.     
  481.     switch (myMenuID) {
  482.     
  483.         case mApple:
  484.             switch (myMenuItem) {
  485.                 case iAbout:    // about box
  486.                     ShowAboutBox();     
  487.                     break;
  488.                 
  489.                 default:         // Apple menu handling
  490.                     GetMenuItemText(GetMenuHandle(mApple), myMenuItem, myDAName);
  491.                     (void)OpenDeskAcc(myDAName);
  492.                     break;
  493.             }
  494.             break;
  495.  
  496.         case mFile:
  497.             switch (myMenuItem) {
  498.                 case iNew:
  499.                     DoCreateNewMovie();
  500.                     break;
  501.                     
  502.                 case iOpen:
  503.                     DoCreateMovieWindow(NULL, NULL);
  504.                     break;
  505.                 
  506.                 case iClose:
  507.                     DoDestroyMovieWindow(GetFrontAppWindow());
  508.                     break;
  509.                 
  510.                 case iSave:
  511.                     DoUpdateMovieFile(GetFrontMovieWindow());
  512.                     break;
  513.                     
  514.                 case iSaveAs:
  515.                     DoSaveAsMovieFile(GetFrontMovieWindow());
  516.                     break;
  517.                                     
  518.                 case iPrint: {
  519.                     MovieController        myMC;
  520.                     OSErr                myErr = noErr;
  521.  
  522.                     myMC = GetMCFromFrontWindow();
  523.                     if (myMC != NULL) {
  524.                         myErr = QTUtils_PrintMoviePICT(MCGetMovie(myMC), kDefaultX, kDefaultY, kPrintFrame); 
  525.                         if (myErr != noErr) {
  526.                             ShowWarning("\pCould not print!", myErr);
  527.                             SysBeep(kDefaultSysBeep);
  528.                         }
  529.                     } else
  530.                         SysBeep(kDefaultSysBeep);
  531.                     break;
  532.                 }
  533.  
  534.                 case iQuit:
  535.                     QuitFramework();
  536.                     break;
  537.                     
  538.             }
  539.             break;
  540.     
  541.         // provide the default controller cut, copy and paste functionality    
  542.         case mEdit: {
  543.             Movie                myMovie = NULL;
  544.             MovieController        myMC = NULL;
  545.             WindowObject        myWindowObject = NULL;
  546.             
  547.             myMC = GetMCFromFrontWindow();
  548.             myWindowObject = GetWindowObjectFromFrontWindow();
  549.             
  550.             if (myMenuItem == iPreferences) {
  551.                 HandleApplicationMenu(MENU_IDENTIFIER(myMenuID, myMenuItem));
  552.                 break;
  553.             }
  554.  
  555.             if ((myMC == NULL) || (myWindowObject == NULL))
  556.                 break;
  557.             
  558.             switch (myMenuItem) {
  559.                 case iUndo:
  560.                     MCUndo(myMC);
  561.                     (**myWindowObject).fDirty = true;
  562.                     break;
  563.                 
  564.                 case iCut:
  565.                     myMovie = MCCut(myMC);
  566.                     (**myWindowObject).fDirty = true;
  567.                     break;
  568.                 
  569.                 case iCopy:
  570.                     myMovie = MCCopy(myMC);
  571.                     break;
  572.                 
  573.                 case iPaste:
  574.                     MCPaste(myMC, NULL);
  575.                     (**myWindowObject).fDirty = true;
  576.                     break;
  577.                 
  578.                 case iClear:
  579.                     MCClear(myMC);
  580.                     (**myWindowObject).fDirty = true;
  581.                     break;
  582.                 
  583.                 case iSelectAll:
  584.                     if (QTUtils_SelectAllMovie(myMC) != noErr)
  585.                         SysBeep(kDefaultSysBeep);
  586.                     break;
  587.             }
  588.             
  589.             if (myMovie) {
  590.                 PutMovieOnScrap(myMovie, 0L);
  591.                 DisposeMovie(myMovie);
  592.             }
  593.             
  594.             break;
  595.         }
  596.  
  597.  
  598.     default:
  599.         // do any application-specific menu handling
  600.         HandleApplicationMenu(MENU_IDENTIFIER(myMenuID, myMenuItem));
  601.         break;
  602.         
  603.     }    // switch (myMenuID)
  604.     
  605.     HiliteMenu(0);
  606. }
  607.  
  608.  
  609. //////////
  610. //
  611. // AdjustMenus
  612. // Adjust the application's File and Edit menus.
  613. //
  614. //////////
  615.  
  616. void AdjustMenus (void)
  617. {
  618.     WindowRef            myWindow = NULL;
  619.     WindowObject        myWindowObject = NULL;
  620.     MovieController        myMC = NULL;
  621.     MenuHandle            myMenu;
  622.  
  623.     myWindow = FrontWindow();
  624.     
  625.     if (myWindow != NULL)
  626.         myWindowObject = GetWindowObjectFromWindow(myWindow);
  627.     
  628.     if (myWindowObject != NULL)
  629.         myMC = (**myWindowObject).fController;
  630.  
  631.     if (myWindow != NULL) {
  632.     
  633.         // handle the File menu's Close command
  634.         EnableItem(GetMenuHandle(mFile), iClose);
  635.         
  636.         if (myWindowObject != NULL) {
  637.         
  638.             // handle the File menu's Save As and Print commands
  639.             EnableItem(GetMenuHandle(mFile), iSaveAs);
  640.             EnableItem(GetMenuHandle(mFile), iPrint);
  641.         
  642.             // let the movie controller do the right thing for the Edit menu
  643.             if (myMC != NULL) {
  644.                 long    myFlags;
  645.             
  646.                 MCSetUpEditMenu(myMC, 0L, GetMenuHandle(mEdit));
  647.                 
  648.                 // MCSetUpEditMenu doesn't handle Select All, so we'll do it ourselves....
  649.                 MCGetControllerInfo(myMC, &myFlags);
  650.                 if (myFlags & mcInfoEditingEnabled)
  651.                     EnableItem(GetMenuHandle(mEdit), iSelectAll);
  652.                 else
  653.                     DisableItem(GetMenuHandle(mEdit), iSelectAll);
  654.             }
  655.             
  656.             // handle the File menu's Save menu command
  657.             if ((**myWindowObject).fDirty)
  658.                 EnableItem(GetMenuHandle(mFile), iSave);
  659.             else
  660.                 DisableItem(GetMenuHandle(mFile), iSave);
  661.         } else {
  662.             // handle the File menu's Save As and Print commands
  663.             DisableItem(GetMenuHandle(mFile), iSaveAs);
  664.             DisableItem(GetMenuHandle(mFile), iPrint);
  665.         }
  666.         
  667.     } else {
  668.         // handle the File menu
  669.         myMenu = GetMenuHandle(mFile);
  670.         DisableItem(myMenu, iSave);
  671.         DisableItem(myMenu, iSaveAs);
  672.         DisableItem(myMenu, iClose);
  673.         DisableItem(myMenu, iPrint);
  674.         
  675.         // handle the Edit menu
  676.         myMenu = GetMenuHandle(mEdit);
  677.         DisableItem(myMenu, iCut);
  678.         DisableItem(myMenu, iCopy);
  679.         DisableItem(myMenu, iPaste);
  680.         DisableItem(myMenu, iUndo);
  681.         DisableItem(myMenu, iClear);
  682.         DisableItem(myMenu, iSelectAll);
  683.     }
  684.     
  685.     AdjustApplicationMenus(myWindow, NULL);                    // adjust any app-specific menus as well
  686. }
  687.  
  688.  
  689. //////////
  690. //
  691. // HandleKeyPress
  692. // Handle key presses. This is modelled on Inside Macintosh: Macintosh Toolbox Essentials, p. 3-78.
  693. //
  694. //////////
  695.  
  696. void HandleKeyPress (EventRecord *theEvent)
  697. {
  698.     char        myKey;
  699.     
  700.     myKey = theEvent->message & charCodeMask;
  701.     
  702.     if (theEvent->modifiers & cmdKey) {
  703.         // if the command key is down, it must be a keyboard shortcut for a menu selection;
  704.         // adjust the menus and find the menu command that the shortcut picks out
  705.         AdjustMenus();
  706.         HandleMenuCommand(MenuKey(myKey));
  707.     } else {
  708.         // otherwise, we'll assume it's meant for our application
  709.         HandleApplicationKeyPress(myKey);
  710.     }
  711. }
  712.  
  713.  
  714. //////////
  715. //
  716. // QuitFramework
  717. // Do any framework-specific shut-down.
  718. //
  719. //////////
  720.  
  721. void QuitFramework (void)
  722. {
  723.     WindowReference            myWindow;
  724.     WindowReference            myNextWindow;
  725.  
  726.     // set quit flag, so we exit the event loop the next time thru
  727.     gQuitFlag = true;
  728.     
  729.     // do any application-specific shutdown: before destroying any open windows
  730.     StopApplication(kStopAppPhase_BeforeDestroyWindows);
  731.     
  732.     // walk the window list and destroy any open windows
  733.     myWindow = GetFrontAppWindow();
  734.     while (myWindow != NULL) {
  735.         myNextWindow = GetNextAppWindow(myWindow);
  736.         DoDestroyMovieWindow(myWindow);
  737.         myWindow = myNextWindow;
  738.     }
  739.     
  740.     // test the quit flag; a call to DoDestroyMovieWindow may have reset it
  741.     if (!gQuitFlag)
  742.         return; 
  743.     
  744.     // do any application-specific shutdown: after destroying any open windows
  745.     StopApplication(kStopAppPhase_AfterDestroyWindows);
  746.     
  747.     // release the grow zone memory
  748.     DisposeHandle(gEmergencyMemory);
  749. }
  750.  
  751.  
  752. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  753. //
  754. // Framework utilities.
  755. //
  756. // The framework uses the following functions to create movies and handle dialog boxes. You probably won't
  757. // need to use them directly.
  758. //
  759. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  760.  
  761. //////////
  762. //
  763. // DoCreateNewMovie
  764. // Create a new movie in a window; returns true if successful.
  765. //
  766. // NOTE: There are several user interface issues that are blissfully ignored by this routine,
  767. // principally the preferred names and the on-screen locations of the new windows. 
  768. //
  769. //////////
  770.  
  771. Boolean DoCreateNewMovie (void)
  772. {
  773.     Movie                myMovie = NULL;
  774.     FSSpec                myFSSpec;
  775.     StringPtr             myName = QTUtils_ConvertCToPascalString(kNewMovieName);
  776.     
  777.     myMovie = NewMovie(newMovieActive);
  778.     if (myMovie == NULL)
  779.         return(false);
  780.     
  781.     // create a default FSSpec
  782.     FSMakeFSSpec(0, 0L, myName, &myFSSpec);
  783.     
  784.     free(myName);
  785.     
  786.     return(DoCreateMovieWindow(myMovie, &myFSSpec));
  787. }
  788.  
  789.  
  790. //////////
  791. //
  792. // SetupMovieWindowWithController
  793. // Configure the movie controller.
  794. //
  795. //////////
  796.  
  797. MovieController SetupMovieWindowWithController (Movie theMovie, WindowReference theWindow, Boolean theMoveWindow)
  798. {
  799.     MovieController            myMC;
  800.     Rect                    myRect;
  801.     WindowObject            myWindowObject;
  802.     GrafPtr                    mySavedPort;
  803.     short                    myMovieWidth;
  804.     short                    myMovieHeight;
  805.     
  806.     myWindowObject = GetWindowObjectFromWindow(theWindow);        // get our window specific data
  807.  
  808.     GetPort(&mySavedPort);
  809.     MacSetPort((GrafPtr)theWindow);
  810.     
  811.     // resize the movie bounding rect and offset to 0,0
  812.     GetMovieBox(theMovie, &myRect);
  813.     MacOffsetRect(&myRect, -myRect.left, -myRect.top);
  814.     SetMovieBox(theMovie, &myRect);
  815.     AlignWindow((WindowPtr)theWindow, false, &myRect, NULL);
  816.  
  817.     // create the movie controller
  818.     myMC = NewMovieController(theMovie, &myRect, gMCFlags);
  819.     if (myMC == NULL)
  820.         return(NULL);
  821.         
  822.     // enable the default movie controller editing
  823.     MCEnableEditing(myMC, true);
  824.         
  825.     // suppress movie badge
  826.     MCDoAction(myMC, mcActionSetUseBadge, (void *)false);
  827.  
  828.     MCGetControllerBoundsRect(myMC, &myRect);
  829.     
  830.     // add grow box for the movie controller
  831.     MCDoAction(myMC, mcActionSetGrowBoxBounds, &gLimitRect);
  832.     
  833.     // set the initial looping state of the movie; this is a nice touch
  834.     QTUtils_SetLoopingStateFromFile(theMovie, myMC);
  835.     
  836.     // install an action filter that does any application-specific mc action processing
  837.     MCSetActionFilterWithRefCon(myMC, NewMCActionFilterWithRefConProc(ApplicationMCActionFilterProc), (long)myWindowObject);
  838.                                                     
  839.     // see if the bounding rects are sane
  840.     myMovieWidth = myRect.right - myRect.left;
  841.     myMovieHeight = myRect.bottom - myRect.top;
  842.     
  843.     // resize the window
  844.     SizeWindow(theWindow, myMovieWidth, myMovieHeight, true);
  845.     if (theMoveWindow)
  846.         MoveWindow(theWindow, kDefaultX, kDefaultY, false);
  847.  
  848.     MacSetPort(mySavedPort);
  849.  
  850.     // add any application-specific controller functionality
  851.     AddControllerFunctionality(myMC);
  852.  
  853.     return(myMC);
  854. }
  855.  
  856.  
  857. //////////
  858. //
  859. // DoCreateMovieWindow
  860. // Open a movie in a new movie window; returns true if successful.
  861. //
  862. // This function is called from several places in our framework. The following combinations are possible:
  863. //    * theMovie == NULL, theFSSpec == NULL: no movie, no file; elicit a movie file from user and open it
  864. //    * theMovie != NULL, theFSSpec == NULL: new movie, no file (yet)
  865. //    * theMovie == NULL, theFSSpec != NULL: no movie, but we have an FSSpec; so just open the specified movie file
  866. //    * theMovie != NULL, theFSSpec != NULL: new movie, theFSSpec contains (at least) the movie name
  867. //
  868. //////////
  869.  
  870. Boolean DoCreateMovieWindow (Movie theMovie, FSSpec *theFSSpec)
  871. {
  872.     WindowObject        myWindowObject = NULL;
  873.     MovieController        myMC = NULL;
  874.     WindowReference        myWindow = NULL;
  875.     FSSpec                myFSSpec;
  876.     Movie                myMovie = NULL;
  877.     short                myRefNum = kInvalidFileRefNum;
  878.     short                myResID = 0;
  879.     SFTypeList            myTypeList = {kQTFileTypeMovie, 0, 0, 0};
  880.     StandardFileReply    myReply;
  881.     Rect                 myRect = gDefaultWindowRect;
  882.     GrafPtr                mySavedPort;
  883.     OSErr                myErr = noErr;
  884.  
  885.     // get the current port; we may need to restore it if we cannot successfully create a new window
  886.     GetPort(&mySavedPort);
  887.     
  888.     // if we got neither a movie nor an FSSpec passed in, prompt the user for a movie file
  889.     if ((theMovie == NULL) && (theFSSpec == NULL)) {
  890.     
  891.         StandardGetFilePreview(NULL, 1, myTypeList, &myReply);
  892.         if (!myReply.sfGood)
  893.             goto bail;
  894.         
  895.         // make an FSSpec record
  896.         FSMakeFSSpec(myReply.sfFile.vRefNum, myReply.sfFile.parID, myReply.sfFile.name, &myFSSpec);
  897.     }
  898.  
  899.     // if we got an FSSpec passed in, copy it into myFSSpec
  900.     if (theFSSpec != NULL) {
  901.     
  902.         // make an FSSpec record
  903.         FSMakeFSSpec(theFSSpec->vRefNum, theFSSpec->parID, theFSSpec->name, &myFSSpec);        
  904.     }
  905.  
  906.     // if we got no movie passed in, read one from the specified file
  907.     if (theMovie == NULL) {
  908.  
  909.         // ideally, we'd like read and write permission, but we'll settle for read-only permission
  910.         myErr = OpenMovieFile(&myFSSpec, &myRefNum, fsRdWrPerm);
  911.         if (myErr != noErr)
  912.             myErr = OpenMovieFile(&myFSSpec, &myRefNum, fsRdPerm);
  913.  
  914.         // if we couldn't open the file with even just read-only permission, bail....
  915.         if (myErr != noErr)
  916.             goto bail;
  917.  
  918.         // now fetch the first movie from the file
  919.         myResID = 0;
  920.         myErr = NewMovieFromFile(&myMovie, myRefNum, &myResID, NULL, newMovieActive, NULL);
  921.         if (myErr != noErr)
  922.             goto bail;
  923.         
  924.         // we will allow the user to edit our files, so we keep the movie file open
  925.         // CloseMovieFile(myRefNum);
  926.         
  927.     } else {
  928.         myMovie = theMovie;
  929.     }
  930.  
  931.     //////////
  932.     //
  933.     // at this point, myMovie is an open movie, but myFSSpec may or may not be a valid FSSpec
  934.     //
  935.     //////////
  936.     
  937.     // set the default progress procedure for the movie
  938.     SetMovieProgressProc(myMovie, (MovieProgressUPP)-1, 0);
  939.         
  940.     // create a new window to display the movie in
  941.     myWindow = CreateMovieWindow(&myRect, gWindowTitle);
  942.     if (myWindow == NULL)
  943.         goto bail;
  944.     
  945.     MacSetPort(GetPortFromWindowReference(myWindow));
  946.     myWindowObject = CreateWindowObject(myWindow);
  947.     if (myWindowObject == NULL)
  948.         goto bail;
  949.     
  950.     // set the window title
  951.     SetWTitle(myWindow, myFSSpec.name);
  952.  
  953.     // make sure the movie uses the window GWorld in all situations
  954.     SetMovieGWorld(myMovie, (CGrafPtr)GetPortFromWindowReference(myWindow), GetGWorldDevice((CGrafPtr)GetPortFromWindowReference(myWindow)));
  955.  
  956.     // create and configure the movie controller
  957.     myMC = SetupMovieWindowWithController(myMovie, myWindow, true);
  958.         
  959.     // store movie info in the window record
  960.     (**myWindowObject).fMovie = myMovie;
  961.     (**myWindowObject).fController = myMC;
  962.     (**myWindowObject).fFileResID = myResID;
  963.     (**myWindowObject).fFileRefNum = myRefNum;
  964.     (**myWindowObject).fCanResizeWindow = true;
  965.     (**myWindowObject).fDirty = false;
  966.     (**myWindowObject).fInstance = NULL;
  967.     (**myWindowObject).fAppData = NULL;
  968.     (**myWindowObject).fFileFSSpec = myFSSpec;
  969.     
  970.     // do any application-specific window object initialization
  971.     InitApplicationWindowObject(myWindowObject);
  972.     
  973.     // size the window to fit the movie and controller
  974.     SizeWindowToMovie(myWindowObject);
  975.  
  976.     // set the movie's play hints to allow dynamic resizing
  977.     SetMoviePlayHints(myMovie, hintsAllowDynamicResize, hintsAllowDynamicResize);
  978.  
  979.     // show the window
  980.     ShowWindow(myWindow);
  981.     SelectWindow(myWindow);                                // make it front-most, since it's just been created
  982.     InvalRect(&((GrafPtr)myWindow)->portRect);
  983.     
  984.     // if the movie is a streamed movie, then start it playing immediately
  985.     if (QTUtils_IsStreamedMovie(myMovie))
  986.         MCDoAction(myMC, mcActionPrerollAndPlay, (void *)GetMoviePreferredRate(myMovie));
  987.         
  988.     return(true);
  989.     
  990. bail:
  991.     if (myWindow != NULL)
  992.         DisposeWindow(myWindow);
  993.         
  994.     if (myMC != NULL)
  995.         DisposeMovieController(myMC);
  996.         
  997.     if (myMovie != NULL)
  998.         DisposeMovie(myMovie);
  999.         
  1000.     if (myRefNum != 0)
  1001.         CloseMovieFile(myRefNum);
  1002.  
  1003.     MacSetPort(mySavedPort);    // restore the port that was active when this function was called
  1004.  
  1005.     return(false);
  1006. }
  1007.  
  1008.  
  1009. //////////
  1010. //
  1011. // DoDestroyMovieWindow
  1012. // Close the specified movie window.
  1013. //
  1014. //////////
  1015.  
  1016. void DoDestroyMovieWindow (WindowReference theWindow)
  1017. {
  1018.     Movie                 myMovie = NULL;
  1019.     MovieController        myMC = NULL;
  1020.     WindowObject        myWindowObject = NULL;
  1021.     
  1022.     // get the window object associated with the specified window
  1023.     myWindowObject = GetWindowObjectFromWindow(theWindow);
  1024.     if (myWindowObject == NULL) {
  1025.         // if the window passed in isn't a movie window, just dispose of it and return
  1026.         if (theWindow != NULL) {
  1027.             DisposeWindow(theWindow);
  1028.             theWindow = NULL;
  1029.         }
  1030.         return;
  1031.     }
  1032.     
  1033.     // if the window's data is "dirty", give the user a chance to save it;
  1034.     // this is modeled on Inside Macintosh: Macintosh Toolbox Essentials, pp. 4-62f.
  1035.     if ((**myWindowObject).fDirty) {
  1036.         Str255            myString;
  1037.         short            myItem;
  1038.         short             mySavedResFile;
  1039.         
  1040.         // get the current resource file and set the application's resource file
  1041.         mySavedResFile = CurResFile();
  1042.         UseResFile(gAppResFile);
  1043.  
  1044.         // get the title of the window
  1045.         GetWTitle(theWindow, myString);
  1046.         
  1047.         // insert the application's name and the window title into the dialog box text
  1048.         ParamText(gAppName, myString, NULL, NULL);
  1049.         
  1050.         // display the "Save changes" dialog box
  1051.         myItem = CautionAlert(kSaveDialogID, gModalFilterUPP);
  1052.         
  1053.         UseResFile(mySavedResFile);                    // restore the original resource file
  1054.         
  1055.         switch (myItem) {
  1056.             case kSaveChanges:
  1057.                 // save the data in the window
  1058.                 DoUpdateMovieFile(theWindow);
  1059.                 break;
  1060.                 
  1061.             case kDontSaveChanges:
  1062.                 // discard any unsaved changes (that is, don't do anything)
  1063.                 break;
  1064.                 
  1065.             case kCancelClose:
  1066.                 // do not close the window, and do not quit the application
  1067.                 gQuitFlag = false;
  1068.                 return;
  1069.         }
  1070.     }
  1071.  
  1072.     myMC = (**myWindowObject).fController;
  1073.     myMovie = (**myWindowObject).fMovie;
  1074.             
  1075.     // remove our mcAction filter function
  1076.     MCSetActionFilterWithRefCon(myMC, NULL, NULL);
  1077.  
  1078.     // close the movie file
  1079.     if ((**myWindowObject).fFileRefNum != kInvalidFileRefNum) {
  1080.         CloseMovieFile((**myWindowObject).fFileRefNum);
  1081.         (**myWindowObject).fFileRefNum = kInvalidFileRefNum;
  1082.     }
  1083.     
  1084.     // order is important here; according to Inside Macintosh: QuickTime, p. 2-96:
  1085.     // "Do not dispose of a movie if it has any special clients--for example,
  1086.     // if it has an attached movie controller component.
  1087.     // Only dispose of the movie after any clients are done with it."
  1088.     if (myMC != NULL)
  1089.         DisposeMovieController(myMC);
  1090.  
  1091.     if (myMovie != NULL)
  1092.         DisposeMovie(myMovie);
  1093.  
  1094.     // do any application-specific window clean-up
  1095.     RemoveApplicationWindowObject(myWindowObject);
  1096.     
  1097.     DisposeHandle((Handle)myWindowObject);
  1098.     DisposeWindow(theWindow);
  1099. }
  1100.  
  1101.  
  1102. //////////
  1103. //
  1104. // DoSaveAsMovieFile
  1105. // Save the movie in the specified window under a new name.
  1106. //
  1107. // Human interface guidelines for "Save As..." dictate that, if the user selects a new file name
  1108. // for the current movie, then that new file shall become the active one. This means that we need
  1109. // to close the current movie file and open the new one.
  1110. //
  1111. //////////
  1112.  
  1113. OSErr DoSaveAsMovieFile (WindowReference theWindow)
  1114. {
  1115.     WindowObject        myWindowObject = NULL;
  1116.     Movie                 myMovie = NULL;
  1117.     StandardFileReply    mySFReply;
  1118.     StringPtr             myPrompt = QTUtils_ConvertCToPascalString(kSavePrompt);
  1119.     StringPtr             myFileName = QTUtils_ConvertCToPascalString(kSaveMovieFileName);
  1120.     OSErr                myErr = paramErr;
  1121.     
  1122.     // get the window object associated with the specified window
  1123.     myWindowObject = GetWindowObjectFromWindow(theWindow);
  1124.     if (myWindowObject == NULL)
  1125.         goto bail;
  1126.         
  1127.     myMovie = (**myWindowObject).fMovie;
  1128.     if (myMovie == NULL)
  1129.         goto bail;
  1130.         
  1131.     StandardPutFile(myPrompt, myFileName, &mySFReply); 
  1132.     if (mySFReply.sfGood) {
  1133.         Movie            myNewMovie = NULL;
  1134.         MovieController    myMC = NULL;
  1135.         long            myFlags;
  1136.         short            myRefNum = kInvalidFileRefNum;
  1137.         short            myResID = movieInDataForkResID;
  1138.         
  1139.         //////////
  1140.         //
  1141.         // we have a valid FSSpec for the new movie file; now we want to create a new movie file,
  1142.         // save the movie data into the new file, close the existing movie file, and then swap
  1143.         // the window object data
  1144.         //
  1145.         //////////
  1146.         
  1147.         // delete any existing file of that name
  1148.         if (mySFReply.sfReplacing) {
  1149.             myErr = DeleteMovieFile(&mySFReply.sfFile);
  1150.             if (myErr != noErr)
  1151.                 goto bail;
  1152.         }
  1153.         
  1154.         myFlags = createMovieFileDeleteCurFile | createMovieFileDontOpenFile | createMovieFileDontCreateMovie | createMovieFileDontCreateResFile;
  1155.         myErr = CreateMovieFile(&mySFReply.sfFile, FOUR_CHAR_CODE('TVOD'), smSystemScript, myFlags, NULL, NULL);
  1156.         if (myErr != noErr)
  1157.             goto bail;
  1158.         
  1159.         myErr = OpenMovieFile(&mySFReply.sfFile, &myRefNum, fsRdWrPerm);
  1160.         if (myErr != noErr)
  1161.             goto bail;
  1162.             
  1163.         // write existing movie's data into new movie file
  1164.         myErr = AddMovieResource(myMovie, myRefNum, &myResID, mySFReply.sfFile.name);
  1165.         if (myErr != noErr)
  1166.             goto bail;
  1167.  
  1168.         // get the new movie from the file
  1169.         myErr = NewMovieFromFile(&myNewMovie, myRefNum, &myResID, NULL, newMovieActive, NULL);        
  1170.         if (myErr != noErr)
  1171.             goto bail;
  1172.         
  1173.         // create a new movie controller
  1174.         myMC = SetupMovieWindowWithController(myNewMovie, theWindow, false);
  1175.         
  1176.         //////////
  1177.         //
  1178.         // if we got to here, we've successfully created a new movie file, and NewMovieFromFile has
  1179.         // returned the new movie to us; so we need to close down the current movie and install the
  1180.         // new movie in its place
  1181.         //
  1182.         //////////
  1183.         
  1184.         // close the existing movie file
  1185.         if ((**myWindowObject).fFileRefNum != kInvalidFileRefNum)
  1186.             CloseMovieFile((**myWindowObject).fFileRefNum);
  1187.         
  1188.         // dispose of the existing movie controller and movie resource
  1189.         DisposeMovieController((**myWindowObject).fController);
  1190.         DisposeMovie(myMovie);
  1191.         
  1192.         // keep track of the new info
  1193.         (**myWindowObject).fMovie = myNewMovie;
  1194.         (**myWindowObject).fController = myMC;
  1195.         (**myWindowObject).fFileFSSpec = mySFReply.sfFile;
  1196.         (**myWindowObject).fFileResID = myResID;
  1197.         (**myWindowObject).fFileRefNum = myRefNum;
  1198.         (**myWindowObject).fDirty = false;
  1199.  
  1200.         // make sure the movie uses the window GWorld in all situations
  1201.         SetMovieGWorld(myNewMovie, (CGrafPtr)GetPortFromWindowReference((**myWindowObject).fWindow), GetGWorldDevice((CGrafPtr)GetPortFromWindowReference((**myWindowObject).fWindow)));
  1202.  
  1203.         // set the window title
  1204.         SetWTitle(theWindow, mySFReply.sfFile.name);
  1205.     } else {
  1206.         myErr = userCanceledErr;
  1207.     }
  1208.  
  1209. bail:
  1210.     free(myPrompt);
  1211.     free(myFileName);
  1212.     
  1213.     return(myErr);
  1214. }
  1215.  
  1216.  
  1217. //////////
  1218. //
  1219. // DoUpdateMovieFile
  1220. // Update the file (if any) attached to the movie.
  1221. //
  1222. //////////
  1223.  
  1224. Boolean DoUpdateMovieFile (WindowReference theWindow)
  1225. {
  1226.     WindowObject        myWindowObject = NULL;
  1227.     Movie                 myMovie = NULL;
  1228.     OSErr                myErr = noErr;
  1229.     
  1230.     // get the window object associated with the specified window
  1231.     myWindowObject = GetWindowObjectFromWindow(theWindow);
  1232.     if (myWindowObject == NULL)
  1233.         return(false);
  1234.         
  1235.     myMovie = (**myWindowObject).fMovie;
  1236.     if (myMovie == NULL)
  1237.         return(false);
  1238.     
  1239.     // update the current volume setting
  1240.     QTUtils_UpdateMovieVolumeSetting(myMovie);
  1241.     
  1242.     if ((**myWindowObject).fFileRefNum == kInvalidFileRefNum)        // brand new movie, so no file attached to it
  1243.         myErr = DoSaveAsMovieFile(theWindow);
  1244.     else                                                            // we have an existing file; just update the movie resource
  1245.         myErr = UpdateMovieResource(myMovie, (**myWindowObject).fFileRefNum, (**myWindowObject).fFileResID, NULL);
  1246.     
  1247.     (**myWindowObject).fDirty = false;
  1248.  
  1249.     return(myErr == noErr);
  1250. }
  1251.  
  1252.  
  1253. //////////
  1254. //
  1255. // DoActivateWindow
  1256. // Activate or deactivate the specified window.
  1257. //
  1258. //////////
  1259.  
  1260. void DoActivateWindow (WindowReference theWindow, Boolean isBecomingActive)
  1261. {
  1262.     WindowObject         myWindowObject = NULL;
  1263.     MovieController        myMC = NULL;
  1264.     GrafPtr                mySavedPort = NULL;
  1265.     
  1266.     if (theWindow == NULL)
  1267.         return;
  1268.     
  1269.     GetPort(&mySavedPort);
  1270.     MacSetPort((GrafPtr)theWindow);
  1271.     
  1272.     // get the window object associated with the specified window
  1273.     myWindowObject = GetWindowObjectFromWindow(theWindow);
  1274.     if (myWindowObject != NULL) {
  1275.         myMC = (**myWindowObject).fController;
  1276.         if (myMC != NULL)
  1277.             MCActivate(myMC, theWindow, isBecomingActive);
  1278.     }
  1279.     
  1280.     MacSetPort(mySavedPort);
  1281. }
  1282.  
  1283.  
  1284. //////////
  1285. //
  1286. // StandardUserItemProcedure
  1287. // A standard user-item procedure to outline the OK button in a modal dialog.
  1288. //
  1289. //////////
  1290.  
  1291. PASCAL_RTN void StandardUserItemProcedure (DialogPtr theDialog, short theItem)
  1292. {
  1293. #pragma unused(theItem)
  1294.  
  1295.     short            myItemKind;        // for GetDialogItem
  1296.     Handle            myItemHandle;    // for GetDialogItem
  1297.     Rect            myItemRect;        // for GetDialogItem
  1298.  
  1299.     if (!gHasNewDialogCalls) {        // no need to do any of this if the new Dialog Manager calls are available
  1300.         GetDialogItem(theDialog, kStdOkItemIndex, &myItemKind, &myItemHandle, &myItemRect);        
  1301.         MacInsetRect(&myItemRect, -4, -4);
  1302.         PenSize(3, 3);
  1303.         FrameRoundRect(&myItemRect, 16, 16);
  1304.         PenSize(1, 1);
  1305.     }
  1306. }
  1307.  
  1308.  
  1309. //////////
  1310. //
  1311. // StandardModalDialogEventFilter
  1312. // A standard modal dialog event filter. 
  1313. //
  1314. //////////
  1315.  
  1316. PASCAL_RTN Boolean StandardModalDialogEventFilter (DialogPtr theDialog, EventRecord *theEvent, short *theItemHit)
  1317. {
  1318.     Boolean                myEventHandled = false;
  1319.     short                myItemKind;            // for GetDialogItem
  1320.     Handle                myItemHandle;        // for GetDialogItem
  1321.     Rect                myItemRect;            // for GetDialogItem
  1322.     unsigned long        myTicks;            // for Delay
  1323.     char                myKey;        
  1324.     WindowReference        myWindow = NULL;
  1325.     ModalFilterUPP        myStdModalProc;        // the OS's standard filter procedure
  1326.     short                myPart;    
  1327.     OSErr                myErr = noErr;
  1328.         
  1329.     switch (theEvent->what) {
  1330.         case updateEvt:
  1331.             // update the specified window, if it's behind the modal dialog
  1332.             myWindow = (WindowReference)theEvent->message;
  1333.             if ((myWindow != NULL) && (myWindow != theDialog)) {
  1334.                 DoUpdateWindow(myWindow, &(**(myWindow->visRgn)).rgnBBox);
  1335.                 myEventHandled = false;        // so sayeth IM
  1336.             }
  1337.             break;
  1338.  
  1339.         case nullEvent:
  1340.             // do idle-time processing for all open windows in our window list
  1341.             myWindow = FrontWindow();
  1342.             while (myWindow != NULL) {
  1343.                 if (gAppInForeground)
  1344.                     DoIdle(myWindow);
  1345.                     
  1346.                 myWindow = (WindowPtr)(((WindowRecord*)myWindow)->nextWindow);
  1347.             }
  1348.             
  1349.             myEventHandled = false;
  1350.             break;
  1351.             
  1352.         case keyDown:
  1353.         case autoKey:
  1354.             // if new Dialog Manager calls are NOT available, handle certain key presses
  1355.             if (!gHasNewDialogCalls) {
  1356.                 // first, map Command-period to Escape key...
  1357.                 myKey = theEvent->message & charCodeMask;
  1358.                 if (theEvent->modifiers & cmdKey)
  1359.                     if (myKey == kPeriod)
  1360.                         myKey = kEscapeKey;
  1361.                         
  1362.                 // ...then, handle the standard keyboard equivalents of OK and Cancel buttons
  1363.                 switch (myKey) {
  1364.                     case kReturnKey:
  1365.                     case kEnterKey:
  1366.                         *theItemHit = kStdOkItemIndex;
  1367.                         GetDialogItem(theDialog, kStdOkItemIndex, &myItemKind, &myItemHandle, &myItemRect);
  1368.                         HiliteControl((ControlHandle)myItemHandle, kControlButtonPart);
  1369.                         Delay(kMyButtonDelay, &myTicks);
  1370.                         HiliteControl((ControlHandle)myItemHandle, false);
  1371.                         myEventHandled = true;
  1372.                         break;
  1373.                     case kEscapeKey:
  1374.                         *theItemHit = kStdCancelItemIndex;
  1375.                         GetDialogItem(theDialog, kStdCancelItemIndex, &myItemKind, &myItemHandle, &myItemRect);
  1376.                         HiliteControl((ControlHandle)myItemHandle, kControlButtonPart);
  1377.                         Delay(kMyButtonDelay, &myTicks);
  1378.                         HiliteControl((ControlHandle)myItemHandle, false);
  1379.                         myEventHandled = true;
  1380.                         break;
  1381.                     default:
  1382.                         break;
  1383.                 }
  1384.             }
  1385.             break;
  1386.             
  1387.         case mouseDown:
  1388.             myPart = FindWindow(theEvent->where, &myWindow);
  1389.             if (myPart == inDrag) {
  1390.                 Rect        myScreenRect;
  1391.                 
  1392.                 myScreenRect = (**GetGrayRgn()).rgnBBox;
  1393.                 DragWindow(myWindow, theEvent->where, &myScreenRect);
  1394.                 myEventHandled = true;
  1395.             }
  1396.             break;
  1397.             
  1398.         default:
  1399.             myEventHandled = false;
  1400.             break;
  1401.     }    
  1402.     
  1403.     // let the OS's standard filter proc handle the event, if it hasn't already been handled
  1404.     if (gHasNewDialogCalls && (myEventHandled == false)) {
  1405.         myErr = GetStdFilterProc(&myStdModalProc);
  1406.         if (myErr == noErr)
  1407.             myEventHandled = CallModalFilterProc(myStdModalProc, theDialog, theEvent, theItemHit);
  1408.     }
  1409.     
  1410.     return(myEventHandled);
  1411. }
  1412.  
  1413.  
  1414. //////////
  1415. //
  1416. // CheckMovieControllers
  1417. // Let all movie controllers have a chance to process the event.
  1418. //
  1419. // Returns true if the event was handled by some movie controller, false otherwise
  1420. //
  1421. //////////
  1422.  
  1423. Boolean CheckMovieControllers (EventRecord *theEvent)
  1424. {    
  1425.     WindowPtr                myWindow;
  1426.     WindowObject            myWindowObject;
  1427.     MovieController            myMC;
  1428.     
  1429.     myWindow = GetFrontMovieWindow();
  1430.     while (myWindow != NULL) {
  1431.          myWindowObject = GetWindowObjectFromWindow(myWindow);
  1432.         if (myWindowObject != NULL) {
  1433.             myMC = (**myWindowObject).fController;
  1434.             if (myMC != NULL)
  1435.                 if (MCIsPlayerEvent(myMC, theEvent))
  1436.                     return(true);
  1437.         }
  1438.         
  1439.         myWindow = GetNextMovieWindow(myWindow);
  1440.     }
  1441.     
  1442.     return(false);
  1443. }
  1444.  
  1445.  
  1446. //////////
  1447. //
  1448. // IsAppWindow
  1449. // Does the specified window belong to our application?
  1450. //
  1451. //////////
  1452.  
  1453. Boolean IsAppWindow (WindowReference theWindow)
  1454. {
  1455.     short            myWindowKind;
  1456.     
  1457.     if (theWindow == NULL) {
  1458.         return(false);
  1459.     } else {
  1460.         myWindowKind = ((WindowPeek)theWindow)->windowKind;
  1461.         return((myWindowKind >= userKind) || (myWindowKind == dialogKind));
  1462.     }
  1463. }
  1464.  
  1465.  
  1466. //////////
  1467. //
  1468. // IsDocWindow
  1469. // Is the specified window a document window (having a WindowObject refcon)?
  1470. //
  1471. //////////
  1472.  
  1473. Boolean IsDocWindow (WindowReference theWindow)
  1474. {
  1475.     short            myWindowKind;
  1476.     
  1477.     if (theWindow == NULL) {
  1478.         return(false);
  1479.     } else {
  1480.         myWindowKind = ((WindowPeek)theWindow)->windowKind;
  1481.         return(myWindowKind >= userKind);
  1482.     }
  1483. }
  1484.  
  1485.  
  1486. //////////
  1487. //
  1488. // CreateWindowObject
  1489. // Create a window object for the specified window.
  1490. //
  1491. //////////
  1492.  
  1493. WindowObject CreateWindowObject (WindowReference theWindow)
  1494. {
  1495.     WindowObject    myWindowObject = NULL;
  1496.     
  1497.     myWindowObject = (WindowObject)NewHandleClear(sizeof(WindowObjectRecord));
  1498.     
  1499.     if (myWindowObject != NULL) {
  1500.         (**myWindowObject).fWindow = theWindow;
  1501.         (**myWindowObject).fController = NULL;
  1502.         (**myWindowObject).fObjectType = kMovieControllerObject;
  1503.         (**myWindowObject).fInstance = NULL;
  1504.         (**myWindowObject).fDirty = false;
  1505.         (**myWindowObject).fAppData = NULL;
  1506.     }
  1507.         
  1508.     SetWRefCon(theWindow, (long)myWindowObject);        // store a ref to the record in the window
  1509.     
  1510.     return(myWindowObject);
  1511. }
  1512.  
  1513.  
  1514. //////////
  1515. //
  1516. // SizeWindowToMovie
  1517. // Set the window size to exactly fit the movie and controller (if visible).
  1518. //
  1519. //////////
  1520.  
  1521. void SizeWindowToMovie (WindowObject theWindowObject)
  1522. {
  1523.     Rect                myMovieBounds;
  1524.     MovieController        myMC = NULL;
  1525.     Movie                myMovie = NULL;
  1526.     
  1527.     if (theWindowObject == NULL)
  1528.         return;
  1529.         
  1530.     myMC = (**theWindowObject).fController;
  1531.     myMovie = (**theWindowObject).fMovie;
  1532.  
  1533.     if (MCGetVisible(myMC))
  1534.         MCGetControllerBoundsRect(myMC, &myMovieBounds);
  1535.     else
  1536.         GetMovieBox(myMovie, &myMovieBounds);
  1537.     
  1538.     // make sure that the movie has a non-zero width;
  1539.     // a zero height is okay (for example, with a music movie with no controller bar)
  1540.     if (myMovieBounds.right - myMovieBounds.left == 0) {
  1541.         myMovieBounds.left = 0;
  1542.         myMovieBounds.right = GetWindowWidth((**theWindowObject).fWindow);
  1543.     }
  1544.         
  1545.     SizeWindow(GetPortFromWindowReference((**theWindowObject).fWindow),
  1546.                                             myMovieBounds.right - myMovieBounds.left,
  1547.                                             myMovieBounds.bottom - myMovieBounds.top,
  1548.                                             true);
  1549. }
  1550.  
  1551.  
  1552. //////////
  1553. //
  1554. // ShowAboutBox
  1555. // Display and manage the About dialog box.
  1556. //
  1557. //////////
  1558.  
  1559. void ShowAboutBox (void)
  1560. {
  1561.     DialogPtr            myDialog = NULL;
  1562.     WindowReference        myWindow = NULL;
  1563.     short                 myItem;
  1564.     short                 mySavedResFile;
  1565.     GrafPtr                mySavedPort;
  1566.     short                myItemKind;
  1567.     Handle                myItemHandle;
  1568.     Rect                myItemRect;
  1569.     
  1570.     // get the current resource file and port
  1571.     mySavedResFile = CurResFile();
  1572.     GetPort(&mySavedPort);
  1573.     
  1574.     // set the application's resource file;
  1575.     // otherwise, we'd get the dialog's resources from the current resource file,
  1576.     // which might not be the correct one....
  1577.     UseResFile(gAppResFile);
  1578.     
  1579.     // deactivate any frontmost movie window
  1580.     myWindow = GetFrontMovieWindow();
  1581.     if (myWindow != NULL)
  1582.         DoActivateWindow(myWindow, false);
  1583.     
  1584.     myDialog = GetNewDialog(kAboutBoxID, NULL, (WindowPtr)-1L);
  1585.     if (myDialog == NULL)
  1586.         goto bail;
  1587.         
  1588.     MacSetPort((GrafPtr)myDialog);
  1589.         
  1590.     if (gHasNewDialogCalls)
  1591.         SetDialogDefaultItem(myDialog, kStdOkItemIndex);
  1592.     
  1593.     // make sure that the OK button is outlined in bold, even if new Dialog Manager calls not available
  1594.     GetDialogItem(myDialog, kOKButtonUserItem, &myItemKind, &myItemHandle, &myItemRect);
  1595.     SetDialogItem(myDialog, kOKButtonUserItem, myItemKind, (Handle)gUserItemProcUPP, &myItemRect);
  1596.  
  1597.     // display and handle events in the dialog box until the user clicks OK
  1598.     do {
  1599.         ModalDialog(gModalFilterUPP, &myItem);
  1600.     } while (myItem != kStdOkItemIndex);
  1601.     
  1602. bail:
  1603.     // restore the previous resource file and port
  1604.     MacSetPort(mySavedPort);
  1605.     UseResFile(mySavedResFile);
  1606.     
  1607.     if (myDialog != NULL)
  1608.         DisposeDialog(myDialog);
  1609. }
  1610.  
  1611.  
  1612. //////////
  1613. //
  1614. // ShowWarning
  1615. // Display a warning box.
  1616. //
  1617. //////////
  1618.  
  1619. void ShowWarning (Str255 theMessage, OSErr theErr)
  1620. {
  1621.     Str255                myString;
  1622.     short                 mySavedResFile;
  1623.     
  1624.     // get the current resource file and set the application's resource file
  1625.     mySavedResFile = CurResFile();
  1626.     UseResFile(gAppResFile);
  1627.  
  1628.     NumToString(theErr, myString);
  1629.     ParamText("\pWarning!", theMessage, theErr ? myString: NULL, NULL);
  1630.     Alert(kAlertErrorID, gModalFilterUPP);
  1631.     
  1632.     // restore the original resource file
  1633.     UseResFile(mySavedResFile);
  1634. }
  1635.  
  1636.  
  1637. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1638. //
  1639. // Window walking utilities.
  1640. //
  1641. // Use these two functions to iterate through all open movie windows belonging to the application.
  1642. //
  1643. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1644.  
  1645. //////////
  1646. //
  1647. // GetFrontMovieWindow
  1648. // Return a reference to the frontmost movie window.
  1649. //
  1650. //////////
  1651.  
  1652. WindowReference GetFrontMovieWindow (void)
  1653. {
  1654.     WindowReference            myWindow = GetFrontAppWindow();
  1655.     
  1656.     while ((myWindow != NULL) && (GetWindowObjectFromWindow(myWindow) == NULL))
  1657.         myWindow = GetNextAppWindow(myWindow);
  1658.  
  1659.     return(myWindow);
  1660. }
  1661.  
  1662.  
  1663. //////////
  1664. //
  1665. // GetNextMovieWindow
  1666. // Return a reference to the next movie window.
  1667. //
  1668. //////////
  1669.  
  1670. WindowReference GetNextMovieWindow (WindowReference theWindow)
  1671. {
  1672.     WindowReference            myWindow = GetNextAppWindow(theWindow);
  1673.  
  1674.     while ((myWindow != NULL) && (GetWindowObjectFromWindow(myWindow) == NULL))
  1675.         myWindow = GetNextAppWindow(myWindow);
  1676.  
  1677.     return(myWindow);
  1678. }
  1679.  
  1680.  
  1681. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1682. //
  1683. // Data retrieval utilities.
  1684. //
  1685. // Use the following functions to retrieve the window object, the application-specific data, or the movie
  1686. // controller that is associated with a window.
  1687. //
  1688. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1689.  
  1690. //////////
  1691. //
  1692. // GetWindowObjectFromFrontWindow
  1693. // Get the window object associated with the front window.
  1694. //
  1695. //////////
  1696.  
  1697. WindowObject GetWindowObjectFromFrontWindow (void)
  1698. {
  1699.     return(GetWindowObjectFromWindow(FrontWindow()));
  1700. }
  1701.  
  1702.  
  1703. //////////
  1704. //
  1705. // GetWindowObjectFromWindow
  1706. // Get the window object associated with the specified window.
  1707. //
  1708. //////////
  1709.  
  1710. WindowObject GetWindowObjectFromWindow (WindowReference theWindow)
  1711. {
  1712.     WindowObject        myWindowObject = NULL;
  1713.  
  1714.     if (!IsAppWindow(theWindow))
  1715.         return(NULL);
  1716.             
  1717.     myWindowObject = (WindowObject)GetWRefCon(theWindow);
  1718.  
  1719.     // make sure this is a window object
  1720.     if (!IsWindowObjectOurs(myWindowObject))
  1721.         return(NULL);
  1722.         
  1723.     return(myWindowObject);
  1724. }
  1725.  
  1726.  
  1727. //////////
  1728. //
  1729. // GetMCFromFrontWindow
  1730. // Get the movie controller (if any) associated with the front window.
  1731. //
  1732. //////////
  1733.  
  1734. MovieController GetMCFromFrontWindow (void)
  1735. {
  1736.     MovieController     myMC = NULL;
  1737.     WindowObject        myWindowObject = NULL;
  1738.         
  1739.     myWindowObject = GetWindowObjectFromFrontWindow();
  1740.     if (myWindowObject != NULL)
  1741.         myMC = (**myWindowObject).fController;
  1742.         
  1743.     return(myMC);
  1744. }
  1745.  
  1746.  
  1747. //////////
  1748. //
  1749. // GetMCFromWindow
  1750. // Get the movie controller (if any) associated with the specified window.
  1751. //
  1752. //////////
  1753.  
  1754. MovieController GetMCFromWindow (WindowReference theWindow)
  1755. {
  1756.     MovieController     myMC = NULL;
  1757.     WindowObject        myWindowObject = NULL;
  1758.         
  1759.     myWindowObject = GetWindowObjectFromWindow(theWindow);
  1760.     if (myWindowObject != NULL)
  1761.         myMC = (**myWindowObject).fController;
  1762.         
  1763.     return(myMC);
  1764. }
  1765.  
  1766.  
  1767. //////////
  1768. //
  1769. // GetQTVRInstanceFromFrontWindow
  1770. // Get the QTVRInstance (if any) associated with the front window.
  1771. //
  1772. //////////
  1773.  
  1774. QTVRInstance GetQTVRInstanceFromFrontWindow (void)
  1775. {
  1776.     QTVRInstance         myInstance = NULL;
  1777.     WindowObject        myWindowObject = NULL;
  1778.  
  1779.     myWindowObject = GetWindowObjectFromFrontWindow();
  1780.     if (myWindowObject != NULL)
  1781.         myInstance = (**myWindowObject).fInstance;
  1782.         
  1783.     return(myInstance);
  1784. }
  1785.  
  1786.  
  1787. //////////
  1788. //
  1789. // GetAppDataFromFrontWindow
  1790. // Get the application-specific data associated with the front window.
  1791. //
  1792. //////////
  1793.  
  1794. Handle GetAppDataFromFrontWindow (void)
  1795. {
  1796.     return(GetAppDataFromWindow(FrontWindow()));
  1797. }
  1798.  
  1799.  
  1800. //////////
  1801. //
  1802. // GetAppDataFromWindow
  1803. // Get the application-specific data associated with the specified window.
  1804. //
  1805. //////////
  1806.  
  1807. Handle GetAppDataFromWindow (WindowReference theWindow)
  1808. {
  1809.     WindowObject        myWindowObject = NULL;
  1810.     
  1811.     myWindowObject = GetWindowObjectFromWindow(theWindow);
  1812.     if (myWindowObject == NULL)
  1813.         return(NULL);
  1814.     else
  1815.         return(GetAppDataFromWindowObject(myWindowObject));
  1816. }
  1817.  
  1818.  
  1819. //////////
  1820. //
  1821. // GetAppDataFromWindowObject
  1822. // Get the application-specific data associated with the specified window object.
  1823. //
  1824. //////////
  1825.  
  1826. Handle GetAppDataFromWindowObject (WindowObject theWindowObject)
  1827. {
  1828.     Handle                myAppData = NULL;
  1829.             
  1830.     // make sure this is a window object belonging to our application
  1831.     if (!IsWindowObjectOurs(theWindowObject))
  1832.         return(myAppData);
  1833.     
  1834.     // get the app data handle from the window object
  1835.     myAppData = (**theWindowObject).fAppData;
  1836.     
  1837.     return(myAppData);
  1838. }
  1839.  
  1840.  
  1841. //////////
  1842. //
  1843. // IsWindowObjectOurs
  1844. // Does the specified window object belong to our application?
  1845. //
  1846. //////////
  1847.  
  1848. Boolean IsWindowObjectOurs (WindowObject theWindowObject)
  1849. {
  1850.     OSType        myType = NULL;
  1851.  
  1852.     if ((theWindowObject == NULL) || (*theWindowObject == NULL))
  1853.         return(false);
  1854.         
  1855.     myType = (**theWindowObject).fObjectType;
  1856.     if (myType == kMovieControllerObject)
  1857.         return(true);
  1858.     else
  1859.         return(false);
  1860. }
  1861.  
  1862.  
  1863. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1864. //
  1865. // Miscellaneous utilities.
  1866. //
  1867. // Use the following functions to play beeps, manipulate menus, and do other miscellaneous things. These
  1868. // functions are intended for use in cross-platform code.
  1869. //
  1870. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1871.  
  1872. //////////
  1873. //
  1874. // DoBeep
  1875. // Beep.
  1876. //
  1877. //////////
  1878.  
  1879. void DoBeep (void)
  1880. {
  1881.     SysBeep(30);
  1882. }
  1883.  
  1884.  
  1885. //////////
  1886. //
  1887. // SetMenuState
  1888. // Set the enabled/disabled state of a menu.
  1889. //
  1890. //////////
  1891.  
  1892. void SetMenuState (MenuReference theMenu, UInt16 theMenuItem, short theState)
  1893. {
  1894. #pragma unused(theMenuItem)
  1895.     SetMenuItemState(theMenu, 0, theState);        // menu item == 0 means the entire menu
  1896. }
  1897.  
  1898.  
  1899. //////////
  1900. //
  1901. // SetMenuItemState
  1902. // Set the enabled/disabled state of a menu item.
  1903. //
  1904. //////////
  1905.  
  1906. void SetMenuItemState (MenuReference theMenu, UInt16 theMenuItem, short theState)
  1907. {
  1908.     if (theState == kEnableMenuItem)
  1909.         EnableItem(theMenu, MENU_ITEM(theMenuItem));
  1910.     else
  1911.         DisableItem(theMenu, MENU_ITEM(theMenuItem));
  1912. }
  1913.  
  1914.  
  1915. //////////
  1916. //
  1917. // SetMenuItemLabel
  1918. // Set the label (that is, the text) of a menu item.
  1919. //
  1920. //////////
  1921.  
  1922. void SetMenuItemLabel (MenuReference theMenu, UInt16 theMenuItem, char *theText)
  1923. {
  1924.     Str255        myString;
  1925.     short        mySIndex, myTIndex;
  1926.  
  1927.     // we need to remove the '&' character while converting to a Pascal string    
  1928.     mySIndex = 1;
  1929.     for (myTIndex = 0; myTIndex < strlen(theText); myTIndex++) {
  1930.         if (theText[myTIndex] != '&') {
  1931.             myString[mySIndex] = theText[myTIndex];
  1932.             mySIndex++;
  1933.         }
  1934.     }
  1935.     
  1936.     myString[0] = mySIndex - 1;
  1937.     
  1938.     SetMenuItemText(theMenu, MENU_ITEM(theMenuItem), myString);
  1939. }
  1940.  
  1941.  
  1942. //////////
  1943. //
  1944. // SetMenuItemCheck
  1945. // Set the check mark state state of a menu item.
  1946. //
  1947. //////////
  1948.  
  1949. void SetMenuItemCheck (MenuReference theMenu, UInt16 theMenuItem, Boolean theState)
  1950. {
  1951.     CheckItem(theMenu, MENU_ITEM(theMenuItem), theState);
  1952. }
  1953.  
  1954.  
  1955. //////////
  1956. //
  1957. // GetPortFromWindowReference 
  1958. // Return the graphics port associated with a window reference.
  1959. //
  1960. //////////
  1961.  
  1962. GrafPtr GetPortFromWindowReference (WindowReference theWindow)
  1963. {
  1964.     return((GrafPtr)theWindow);
  1965. }
  1966.  
  1967.  
  1968. //////////
  1969. //
  1970. // GetWindowReferenceFromPort
  1971. // Return the window reference associated with a graphics port.
  1972. //
  1973. //////////
  1974.  
  1975. WindowReference GetWindowReferenceFromPort (GrafPtr thePort)
  1976. {
  1977.     return((WindowReference)thePort);
  1978. }
  1979.  
  1980.  
  1981. //////////
  1982. //
  1983. // GetWindowWidth
  1984. // Return the width of the specified window.
  1985. //
  1986. //////////
  1987.  
  1988. short GetWindowWidth (WindowReference theWindow)
  1989. {
  1990.     short        myWidth = 0;
  1991.     
  1992.     if (theWindow != NULL)
  1993.         myWidth = (theWindow)->portRect.right - (theWindow)->portRect.left;
  1994.  
  1995.     return(myWidth);
  1996. }
  1997.  
  1998.  
  1999. //////////
  2000. //
  2001. // GetFrontAppWindow
  2002. // Return a reference to the frontmost window (whether or not it's a movie window).
  2003. //
  2004. //////////
  2005.  
  2006. WindowReference GetFrontAppWindow (void)
  2007. {
  2008.     return(FrontWindow());
  2009. }
  2010.  
  2011.  
  2012. //////////
  2013. //
  2014. // GetNextAppWindow
  2015. // Return a reference to the next window (whether or not it's a movie window).
  2016. //
  2017. //////////
  2018.  
  2019. WindowReference GetNextAppWindow (WindowReference theWindow)
  2020. {
  2021.     if (theWindow != NULL)
  2022.         return((WindowPtr)(((WindowRecord*)theWindow)->nextWindow));
  2023.     else
  2024.         return(NULL);
  2025. }
  2026.